home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / NCSA⁄BYU TCP⁄IP / userd.c.original < prev    next >
Text File  |  1991-08-08  |  36KB  |  1,643 lines

  1. /*
  2. *  USER.C
  3. *  Network library interface routines
  4. *  Generally called by the session layer
  5. *
  6. ****************************************************************************
  7. *                                                                          *
  8. *      part of:                                                            *
  9. *      TCP/IP kernel for NCSA Telnet                                       *
  10. *      by Tim Krauskopf                                                    *
  11. *                                                                          *
  12. *      National Center for Supercomputing Applications                     *
  13. *      152 Computing Applications Building                                 *
  14. *      605 E. Springfield Ave.                                             *
  15. *      Champaign, IL  61820                                                *
  16. *                                                                          *
  17. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  18. *                                                                          *
  19. ****************************************************************************
  20. *  Revisions:
  21. *  10/87  Initial source release, Tim Krauskopf
  22. *  2/88  typedef support for other compilers (TK)
  23. *  8/88  Gaige Paulsen - support for MacTCP drivers
  24. *  1/89  TK - conversion to new drivers, minor update for new calling convention
  25. *  6/89  TK - update to MacTCP 1.0 include files and use of GetMyIPAddr()
  26. *
  27. */
  28.  
  29. #include <Dialogs.h>
  30. #include <Devices.h>
  31. #include <Memory.h>
  32. #include <MacTCPCommonTypes.h>
  33. #include <TCPPB.h>
  34. #include <UDPPB.h>
  35.  
  36. #define MASTERDEF 1
  37. #include <stdio.h>
  38. #include <String.h>
  39. #include "protocol.h"
  40. #include "data.h"
  41. #include "configrec.h"
  42. #include "maclook.h"
  43. #include "menu.h"
  44. #include "tools.h"
  45. #include <getmyipaddr.h>
  46.  
  47. int EtherNet = -99;        /* Signify Drivers */
  48.  
  49. #define LOWWATER 600
  50.  
  51. pascal void TCPNotify();
  52. pascal void UDPNotify();
  53. long openComplete();
  54. long closeComplete();
  55. long sendComplete();
  56.  
  57. /*
  58.  * UDP Stuff
  59.  */
  60.  
  61. #define    UDPBUFSIZ    (1024*8)
  62. #define    getUPB(x,y,z,a)    (UDPiopb *)getPB(x,y,z,a)
  63.  
  64. typedef struct UDPRec {
  65.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  66.     char   *buffer;                    /* Where the immovable UDP buffer is */
  67.     uint    port;                    /* Which UDP port to use */
  68.     } UDPRec, *UDPRPtr;
  69.  
  70. UDPRPtr uport[ NPORTS];                /* our wonderful little thingies. */
  71.  
  72. /*
  73.  * TCP Stuff
  74.  */
  75. #define    noError    0
  76. #define TCPBUFSIZ    (1024*8)
  77. #define    MAX_FDS_ELEMS    32
  78. #define    MAX_SWDS_ELEMS    16
  79. #define MAX_FREE_PB        128
  80. #define MAX_FREE_SWDS    64
  81.  
  82. #define    Qcall    true
  83. #define    noQcall    false
  84.  
  85. returnPB(TCPiopb *);
  86.  
  87.  
  88. typedef    struct freeEntry {
  89.     int inuse;                        /* is this being used? */
  90.     Ptr    ptr;                        /* Pointer to the free entry */
  91.     } freeEntry;
  92.     
  93. typedef struct exfds {
  94.     int    inuse;                        /* Is this being used */
  95.     wdsEntry fds;                    /* The real data */
  96.     } exfds;
  97.     
  98. typedef struct StreamRec {
  99.     StreamPtr stream;                /* Apple's lovely Stream Pointer */
  100.     char   *buffer;                    /* Where the immovable TCP buffer is */
  101.     int        push;                    /* TRUE if we should push next data block */
  102.     char   *sbuffer;                /* Where the send buffer is */
  103.     wdsEntry    fds[MAX_FDS_ELEMS];    /* Free Data Structure list */
  104.     exfds    exFDS[MAX_FDS_ELEMS];    /* exFDS entries */
  105.     int        maxFDSused;                /* Max of the FDS's that have been used */
  106.     } StreamRec, *StreamRPtr;
  107.     
  108. short TCPd = 0;                        /* refnum of TCP drivers */
  109.  
  110. StreamRPtr streams[NPORTS];
  111.  
  112. int numPB=0;                        /* Number of PB's ever allocated  (Perf. mon. only ) */
  113. int numSWDS=0;                        /* Number of SWDS's ever alloc'd (PM Only) */
  114.  
  115. freeEntry    freePB[ MAX_FREE_PB];
  116. freeEntry    freeSWDS[ MAX_FREE_SWDS];
  117.  
  118. /**************************************************************************/
  119. wdsEntry *getSWDS
  120.   (
  121.     void
  122.   )
  123. {
  124.     int n=0;
  125.     
  126.     while (freeSWDS[n].inuse &&  n<MAX_FREE_SWDS) n++;
  127.     if (n >= MAX_FREE_SWDS)
  128.         return((wdsEntry *) 0L);
  129.     
  130.     freeSWDS[n].inuse=1;
  131.     if (freeSWDS[n].ptr==0L) {
  132.  
  133.         freeSWDS[n].ptr = NewPtr ( sizeof(wdsEntry) *MAX_SWDS_ELEMS);
  134.         numSWDS++;
  135. /*        sprintf(temp,"New SWDS(%d)",numSWDS);
  136.         putln(temp); */
  137.         }
  138.     return((wdsEntry *) freeSWDS[n].ptr);
  139. }
  140.  
  141. /**************************************************************************/
  142. returnSWDS( wds)
  143. wdsEntry *wds;
  144. {
  145.     int n=0;
  146.     
  147.     while (freeSWDS[n].ptr != wds && n<MAX_FREE_SWDS) n++;
  148.     if (n >= MAX_FREE_SWDS)
  149.         return(-1);
  150.     freeSWDS[n].inuse=0;
  151. }
  152.  
  153.  
  154. /**************************************************************************/
  155. TCPiopb *getPB( driver, call, stream, usernum)
  156. int driver, call, usernum;
  157. unsigned long stream;
  158. {
  159. #pragma unused(usernum)
  160.     TCPiopb *pbp;
  161.     int n=0;
  162.     int i;
  163.     
  164.     while (freePB[n].inuse &&  n<MAX_FREE_PB) n++;
  165.  
  166.  
  167.     if (n >= 100)    /* recycle memory so system doesn't get hammered */
  168.         {
  169.         for (i = 0;i < 100;i++)
  170.             {
  171.             if ((freePB[i].inuse) && !(((TCPiopb *)(freePB[i].ptr))->ioResult) )
  172.                 {
  173.                 returnPB((TCPiopb *)freePB[i].ptr); /* re-use this one */
  174.                 n--;                     /* so there is now one less */
  175.                 }
  176.             }
  177.         }
  178.         
  179.     if (n >= MAX_FREE_PB) return(0L);    /* hammer system */
  180.     
  181.     freePB[n].inuse = 1;                
  182.     if (freePB[n].ptr==0L) {
  183.         
  184.         freePB[n].ptr = NewPtr ( sizeof(TCPiopb)+sizeof(int) );
  185.         numPB++;
  186. /*        sprintf(temp,"New PB(%d)",numPB);
  187.         putln(temp); */
  188.         }
  189.     (Ptr) pbp = freePB[n].ptr;
  190.  
  191.  
  192.     if (!pbp) {
  193.         putln("GETPB failed! panic! ");
  194.         quit();
  195.         }
  196.     
  197.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  198.     
  199.     pbp->ioCRefNum = driver;
  200.     pbp->tcpStream=stream;
  201.     pbp->csCode = call;
  202.     
  203.     return(pbp);
  204. }
  205.  
  206. /**************************************************************************/
  207. clearPB( pbp, driver, call, stream, usernum)
  208. TCPiopb *pbp;
  209. int driver, call, usernum;
  210. unsigned long stream;
  211. {
  212. #pragma unused(usernum)
  213.     memset( pbp, '\0', sizeof(TCPiopb)+sizeof(int));    /* Default to all zeros */
  214.     
  215.     pbp->ioCRefNum = driver;
  216.     pbp->tcpStream=stream;
  217.     pbp->csCode = call;
  218.     
  219. }
  220.  
  221. returnPB( pbp)
  222. TCPiopb *pbp;
  223. {
  224.     int n=0;
  225.     
  226.     while (freePB[n].ptr != pbp && n<MAX_FREE_PB) n++;
  227.     if (n >= MAX_FREE_PB)
  228.         return(-1);
  229.     freePB[n].inuse=0;
  230.     
  231. }
  232.  
  233. /***************************************************************************/
  234. /*  netread
  235. *   Read from a connection buffer into a user buffer.  
  236. *   Returns number of bytes read, < 0 on error
  237. * NOTE:
  238. *    current version very inefficient, but hopefully works.
  239. */
  240. netread(pnum,buffer,n)
  241.     int pnum,n;
  242.     char *buffer;
  243.     {
  244.     int i;
  245.     StreamRPtr p;
  246.     TCPiopb *pbp;
  247.     int inQ, reqdamt;
  248.     
  249.     if (pnum < 0)            /* check validity */
  250.         return(-2);
  251.  
  252.     if (NULL == (p = streams[pnum]))
  253.         return(-2);
  254.     
  255.     
  256.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  257.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  258.         putln("TCPStatus failed(read)"); return(-1);
  259.         }
  260. #ifdef DEBUGHEADERS    
  261.     { char temp[100];
  262.         sprintf(temp, "Stat: %x(%d)->%x(%d) <%d,%d,%d> [%d,%d] {%d,%d}",
  263.             (int)pbp->csParam.status.remoteHost,
  264.             (int)pbp->csParam.status.remotePort,
  265.             (int)pbp->csParam.status.localHost,
  266.             (int)pbp->csParam.status.localPort,
  267.             (int)pbp->csParam.status.tosFlags,
  268.             (int)pbp->csParam.status.precedence,
  269.             (int)pbp->csParam.status.connectionState,
  270.             (int)pbp->csParam.status.sendWindow,
  271.             (int)pbp->csParam.status.rcvWindow,
  272.             (int)pbp->csParam.status.amtUnackedData,
  273.             (int)pbp->csParam.status.amtUnreadData);
  274.         putln(temp);
  275.     }
  276. #endif DEBUGHEADERS
  277.     
  278.     if (pbp->csParam.status.connectionState !=8) {
  279.         char temp[50];
  280.         sprintf(temp,"CState: %d is %d",(int)pnum, (int)pbp->csParam.status.connectionState);
  281.         putln(temp);
  282.         return(-1);                              /* Connection not established */
  283.         }
  284.     
  285.     inQ = pbp->csParam.status.amtUnreadData;
  286.     reqdamt = n >inQ ? inQ : n;
  287.     
  288.     clearPB( pbp, TCPd, TCPRcv, p->stream, pnum);
  289.     pbp->csParam.receive.rcvBuff = buffer;
  290.     pbp->csParam.receive.rcvBuffLen = reqdamt;
  291.     
  292.     if (reqdamt<1) {                                /* Drop out if no data */
  293.         returnPB(pbp);
  294.         return(0);
  295.         }
  296.     
  297.     if ((i = PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  298.         char temp[100];
  299.         sprintf(temp,"TCPRcv failed (%d)",i);
  300.         putln( temp);
  301.         return(-1);
  302.         }
  303.         
  304.     reqdamt = pbp->csParam.receive.rcvBuffLen;
  305.     if (reqdamt<inQ) {
  306.         netputuev( CONCLASS, CONDATA, pnum);            /* more data to get */
  307.         }
  308.         
  309.     returnPB(pbp);                    /* Trash PB */
  310. #ifdef TESTINGPARMS
  311.     {
  312.         char temp[100];
  313.         sprintf(temp, "NETRead: %d from %d", reqdamt, pnum);
  314.         putln(temp);
  315.     }
  316. #endif TESTINGPARMS
  317.     return(reqdamt);
  318. }
  319.  
  320. /**************************************************************************/
  321. /* 
  322.  *    reclaim( p) -
  323.  *        reclaims buffer space to stream (from pointer p) into the FDS list 
  324.  */
  325.  
  326. reclaim(p)
  327. StreamRPtr p;
  328. {
  329.     int n=0, offset=0;
  330.     
  331.     while (offset < MAX_FDS_ELEMS && p->fds[offset].ptr != 0L) offset++;
  332.     
  333.     if (offset >= MAX_FDS_ELEMS) {
  334.         putln("Couldn't reclaim because offset was too large ");
  335.         return(0);
  336.         }
  337.     for (n=0 ; n<MAX_FDS_ELEMS && offset< MAX_FDS_ELEMS; n++) {
  338.         if (p->exFDS[ n].inuse) {
  339.             p->fds[ offset++]=p->exFDS[ n].fds;
  340.             p->exFDS[ n].inuse = 0;
  341.             }
  342.         }
  343. }
  344.  
  345. /**************************************************************************/
  346. /*
  347.  *     compressfds( fds)
  348.  *        compress an fds data structure to make everyone happy
  349.  */
  350.  
  351. compressfds( fds)
  352. wdsEntry *fds;
  353. {
  354.     int n,m,compressed;
  355.     
  356.     compressed = 0;
  357.     
  358.     while ( !compressed) {
  359.         compressed=1;
  360.         for (n=0; n< MAX_FDS_ELEMS; n++) {                /* Slow Forwards */
  361.             if (fds[n].ptr) {                                /* Do if N exists */
  362.                 for ( m = MAX_FDS_ELEMS -1; m>=0; m--) {    /* Fast Backwards */
  363.                     if (fds[m].ptr && (fds[m].ptr+fds[m].length == fds[n].ptr)) {
  364.                         fds[n].length+=fds[m].length;
  365.                         fds[n].ptr = fds[m].ptr;
  366.                         fds[m].ptr=0L;
  367.                         fds[m].length=0;
  368.                         compressed=0;
  369.                         }
  370. #ifdef CHECKBOTHWAYZ
  371.                     else 
  372.                     if (fds[n].ptr+fds[n].length == fds[m].ptr) {
  373.                         fds[m].length+=fds[n].length;
  374.                         fds[n].ptr=0L;
  375.                         fds[n].length=0;
  376.                         compressed=0;
  377.                         }
  378. #endif CHECKBOTHWAYZ
  379.                     }
  380.                 }
  381.             }
  382.         }
  383.     m=0;n=0;
  384.     
  385.     /* Close the gaps */
  386.     
  387.     while (n+m < MAX_FDS_ELEMS) {
  388.         while (fds[n+m].ptr ==0L && n+m< MAX_FDS_ELEMS) {
  389.             m++;            /* increase gap to valid entry */
  390.             }
  391.         if (n+m<MAX_FDS_ELEMS)
  392.             fds[n]=fds[n+m];
  393.         n++;
  394.         }
  395.     
  396.     /* Get rid of the empty spaces */
  397.     
  398.     n--;        /* for the next loop */
  399.     while (n < MAX_FDS_ELEMS) {
  400.         fds[n].ptr=0; fds[n++].length=0;
  401.         }
  402. }
  403.  
  404. /************************************************************************/
  405. /* netwrite
  406. *  write something into the output queue, netsleep routine will come
  407. *  around and send the data, etc.
  408. *
  409. */
  410. netwrite(pnum,buffer,nsend)
  411.     int pnum,nsend;
  412.     char *buffer;
  413.     {
  414.     StreamRPtr p;
  415.     wdsEntry *swds;
  416.     int remaining, queued, n,m;
  417.     TCPiopb *pbp;
  418.     
  419.     if (pnum < 0)
  420.         return(-2);
  421.  
  422.     if ( (p = streams[pnum]) == NULL)
  423.         return(-2);
  424.     
  425.     if ( !nsend )
  426.         return(0);
  427.         
  428.     swds = getSWDS();
  429.     
  430.     reclaim( p);
  431.     compressfds( p->fds);
  432.  
  433.     n=0; remaining = nsend;
  434.     while (p->fds[n].ptr !=0 && remaining>0 ) {
  435.         swds[n].ptr = p->fds[n].ptr;
  436.         if ( p->fds[n].length > remaining) {
  437.             swds[n].length = remaining;
  438.             p->fds[n].length -= remaining;
  439.             p->fds[n].ptr += remaining;
  440.             remaining=0;
  441.             }
  442.         else {
  443.             swds[n].length =  p->fds[n].length;
  444.             remaining -= p->fds[n].length;
  445.             p->fds[n].length = 0;
  446.             p->fds[n].ptr = 0;
  447.             }
  448.         n++;
  449.         }
  450.     if (n>p->maxFDSused) p->maxFDSused=n;
  451.     
  452.     compressfds( p->fds);
  453.     queued = nsend-remaining;
  454.     
  455.     for (m=0; m<n; m++) {
  456.         memcpy( swds[m].ptr, buffer, swds[m].length);    /* Put data in WDS */
  457.         buffer +=swds[m].length;
  458.         }
  459.     swds[m].ptr =0L;
  460.     swds[m].length=0;
  461.     
  462.     pbp=getPB( TCPd, TCPSend, p->stream, pnum);            /* Make send call */
  463.     pbp->csParam.send.wdsPtr = (Ptr) swds;
  464.     pbp->csParam.send.pushFlag = p->push;
  465.     
  466.     pbp->ioCompletion = (TCPIOCompletionProc) sendComplete;                    /* Completion routine */
  467.  
  468.     p->push=0;
  469.  
  470.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  471.         putln("TCPSend failed to Q"); return(-1);
  472.         }
  473.     
  474. #ifdef TESTINGPARMS
  475.     putln("TCP Sent");
  476.     { char temp[100];
  477.         sprintf(temp, "TCP Sent: %d of %d on %d [%d/%d]", queued, nsend, pnum,n,p->maxFDSused);
  478.         putln(temp);
  479.     }
  480. #endif TESTINGPARMS
  481.     return(queued);
  482. }
  483.  
  484. /**************************************************************************/
  485. /*  netpush
  486. *   attempt to push the rest of the data from the queue
  487. *   and then return whether the queue is empty or not (0 = empty)
  488. *   returns the number of bytes in the queue.
  489. */
  490. netpush(pnum)
  491.     int pnum;
  492.     {
  493.     StreamRPtr p;
  494.     TCPiopb *pbp;
  495.     int inQ;
  496.     
  497.     if (pnum < 0)
  498.         return(-2);
  499.  
  500.     if (NULL == (p = streams[pnum]))
  501.         return(-2);
  502.  
  503.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  504.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  505.         putln("TCPStatus failed(push)"); return(-1);
  506.         }
  507.     inQ = pbp->csParam.status.amtUnackedData;
  508.     returnPB( pbp);
  509.     
  510.     p->push=1;
  511.     
  512.     return(inQ);
  513.  
  514. }    
  515.  
  516. /**************************************************************************/
  517. /*  netqlen
  518. *   return the number of bytes waiting to be read from the incoming queue.
  519. */
  520. netqlen(pnum)
  521.     int pnum;
  522.     {
  523.     StreamRPtr p;
  524.     TCPiopb *pbp;
  525.     int inQ;
  526.     
  527.     if (pnum < 0)
  528.         return(-2);
  529.  
  530.     if (NULL == (p = streams[pnum]))
  531.         return(-2);
  532.  
  533.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  534.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  535.         putln("TCPStatus failed(qlen)"); return(-1);
  536.         }
  537.     inQ = pbp->csParam.status.amtUnreadData;
  538.     returnPB( pbp);
  539.     
  540.     p->push = 1;
  541.     return(inQ);
  542. }
  543.  
  544. /**************************************************************************/
  545. /*  netroom()
  546. *    return how much room is available in output buffer for a connection
  547. */
  548. netroom(pnum)
  549.     int pnum;
  550.     {
  551.     StreamRPtr p;
  552.     TCPiopb *pbp;
  553.     int inQ,n;
  554.     
  555.     if (pnum < 0)
  556.         return(-2);
  557.  
  558.     if (NULL == (p = streams[pnum]))
  559.         return(-2);
  560.  
  561.     reclaim( p);
  562.     compressfds( p->fds);
  563.  
  564. #ifdef OLDM
  565.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  566.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  567.         putln("TCPStatus failed(room)"); return(-1);
  568.         }
  569.     inQ = pbp->csParam.status.sendWindow -
  570.                 pbp->csParam.status.amtUnackedData;
  571.     returnPB( pbp);
  572. #else
  573. #pragma unused(pbp)
  574. #endif
  575.  
  576.     inQ = n = 0;
  577.     while (p->fds[n].ptr) {
  578.     
  579.         inQ += p->fds[n].length;                /* add up free list space */
  580.         n++;
  581.         }
  582.  
  583.     return(inQ);
  584. }
  585.  
  586. /**************************************************************************/
  587. /* netsegsize and neterrchange and netsetip and netgetip
  588. *
  589. *  set operating parameters to change them from the default values used.
  590. */
  591.  
  592. netsegsize(newsize)
  593.     int newsize;
  594.     {
  595.     int i;
  596.  
  597.     i = nnsegsize;
  598.     nnsegsize = newsize;
  599.  
  600.     return(i);
  601. }
  602.  
  603. /**************************************************************************/
  604. netquench(newcredit)
  605.     int newcredit;
  606.     {
  607.     int i;
  608.  
  609.     i = nncredit;
  610.     nncredit = newcredit;
  611.  
  612.     return(i);
  613. }
  614.  
  615. /**************************************************************************/
  616. netarptime(t)                    /* dlayer timeout in secs */
  617.     int t;
  618.     {
  619.     nndto = t;
  620. }
  621.  
  622. /**************************************************************************/
  623. void netsetip
  624.   (
  625.     unsigned char *st
  626.   )
  627.     {
  628. /*
  629. *  this is a no-op with the MacTCP driver
  630. */
  631. #pragma unused(st)
  632. }
  633.  
  634. /**************************************************************************/
  635. int netgetip
  636.   (
  637.     unsigned char *st
  638.   )
  639. {
  640.     struct IPParamBlock mypb;
  641.     /* long netmask; */
  642.  
  643.     putln("Attempting getmyipaddr");
  644.     
  645.     memset( &mypb, '\0', sizeof(struct IPParamBlock));    /* Default to all zeros */
  646.     
  647.     mypb.ioCRefNum = TCPd;            /* TCP driver has to be open by now */
  648.     mypb.csCode = ipctlGetAddr;
  649.  
  650.     if (PBControl((ParmBlkPtr) &mypb, noQcall) != noError) {
  651.         putln("Getting my address failed"); 
  652.         return(-1);
  653.         }
  654.     
  655.     memcpy(st, &mypb.ourAddress, 4);    /* copy the address */
  656.     
  657.     /* netmask is here if we want it, too */
  658.     
  659.     return(0);
  660.  
  661. }
  662.  
  663.  
  664. /**************************************************************************/
  665. netsetmask(st)
  666. unsigned char *st;
  667. {
  668.     movebytes(nnmask,st,4);
  669. }
  670.  
  671. /**************************************************************************/
  672. netgetmask(st)
  673. unsigned char *st;
  674. {
  675.     movebytes(st,nnmask,4);
  676. }
  677.  
  678. netfromport(port)            /* next "open" will use this port */
  679. int16 port;
  680. {
  681.     nnfromport = port;
  682.  
  683. }
  684.  
  685. /**************************************************************************/
  686. /*  netest?
  687. *  is a particular session established yet?
  688. *  Returns 0 if the connection is in the established state.
  689. */
  690. netest(pnum)
  691. int pnum;
  692. {
  693.     StreamRPtr p;
  694.     TCPiopb *pbp;
  695.     int inQ;
  696.     
  697.     if (pnum < 0)
  698.         return(-2);
  699.  
  700.     if (NULL == (p = streams[pnum]))
  701.         return(-2);
  702.  
  703.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  704.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  705.         putln("TCPStatus failed(est)");
  706.         inQ = -1;
  707.         }
  708.     else 
  709.         inQ = pbp->csParam.status.connectionState !=8;
  710.     returnPB( pbp);
  711.     
  712.     return(inQ);
  713.  
  714. }
  715.  
  716. /**************************************************************************/
  717. /*
  718.  * Returns an empty stream
  719.  */ 
  720. makestream()
  721. {
  722.     int    pnum;
  723.     StreamRPtr p;
  724.     TCPiopb *pbp;
  725.     int i;
  726.     
  727.     for ( pnum=0; streams[pnum]!= NULL && pnum<NPORTS; pnum++);
  728.     
  729.     if (pnum >= NPORTS)
  730.         return(-2);
  731.  
  732.     p = streams[pnum] = (StreamRPtr) NewPtr(sizeof(StreamRec));
  733.  
  734.     if ((p->buffer = (char *) NewPtr( TCPBUFSIZ)) == (char *)NULL)
  735.         return(-1);
  736.     if ((p->sbuffer = (char *) NewPtr( TCPBUFSIZ)) == (char *)NULL)
  737.         return(-1);
  738.     
  739.     for (i=0; i<MAX_FDS_ELEMS; i++) {
  740.         p->fds[ i].length =0; p->fds[ i].ptr = 0L;
  741.         p->exFDS[ i].inuse=0; p->exFDS[ i].fds.length=0;p->exFDS[ i].fds.ptr=0L;
  742.         }
  743.     p->fds[0].length = TCPBUFSIZ;
  744.     p->fds[0].ptr = p->sbuffer;
  745.     p->maxFDSused=0;
  746.     
  747.     pbp=getPB( TCPd, TCPCreate, 0, pnum);            /* Make create call */
  748.     pbp->csParam.create.rcvBuff = p->buffer;
  749.     pbp->csParam.create.rcvBuffLen = TCPBUFSIZ;
  750.     pbp->csParam.create.notifyProc = TCPNotify;
  751.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  752.         putln("TCPCreate failed"); return(-1);
  753.         }
  754.     
  755.     p->stream = pbp->tcpStream;
  756.     
  757.     putln("Made a new stream");
  758.     returnPB(pbp);
  759.     return(pnum);
  760. }
  761.  
  762. /**************************************************************************/
  763. /*  netlisten
  764. *   Listen to a TCP port number and make the connection automatically when
  765. *   the SYN packet comes in.  The TCP layer will notify the higher layers
  766. *   with a CONOPEN event.  Save the port number returned to refer to this
  767. *   connection.
  768. *
  769. *   usage:   portnum = netlisten(service);
  770. *            int service;
  771. *
  772. */
  773. netlisten(serv)
  774. uint serv;
  775. {
  776.     int    pnum;
  777.     StreamRPtr p;
  778.     TCPiopb *pbp;
  779.  
  780.     pnum = makestream();
  781.  
  782.     if (pnum < 0)
  783.         return(-2);
  784.  
  785.     if (NULL == (p = streams[pnum]))
  786.         return(-2);
  787.  
  788.     pbp=getPB( TCPd, TCPPassiveOpen, p->stream, pnum);            /* Make Listen call */
  789.     
  790.     pbp->csParam.open.localPort = serv;
  791.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;        /* IO Completion for open */
  792.     
  793.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  794.         putln("TCPListen failed"); return(-1);
  795.         }
  796.         
  797.     return(pnum);
  798. }
  799.  
  800. /***********************************************************************/
  801. /*  netgetftp
  802. *  Provides the information that ftp needs to open a stream back to the
  803. *  originator of the command connection.  The other side's IP number
  804. *  and the port numbers to be used to calculate the default data connection
  805. *  number.  Returns values in an integer array for convenient use in 
  806. *  PORT commands.
  807. */
  808. netgetftp(a,pnum)
  809. int a[];
  810. int pnum;
  811. {
  812.     StreamRPtr p;
  813.     TCPiopb *pbp;
  814.     long temp;
  815.     
  816.     if (pnum < 0)
  817.         return(-2);
  818.  
  819.     if (NULL == (p = streams[pnum]))
  820.         return(-2);
  821.  
  822.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  823.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  824.         putln("TCPStatus failed(getftp)"); return(-1);
  825.         }
  826.  
  827.     temp      = pbp->csParam.status.remoteHost;
  828.     a[0]= (temp>>24) & 0xff;
  829.     a[1]= (temp>>16) & 0xff;
  830.     a[2]= (temp>> 8) & 0xff;
  831.     a[3]= (temp    ) & 0xff;
  832.     temp    = pbp->csParam.status.localPort;
  833.     a[4]= (temp>> 8) & 0xff;
  834.     a[5]= (temp    ) & 0xff;
  835.     temp    = pbp->csParam.status.remotePort;
  836.     a[6]= (temp>> 8) & 0xff;
  837.     a[7]= (temp    ) & 0xff;
  838.  
  839.     returnPB( pbp);
  840. }
  841.  
  842.  
  843. /**************************************************************************/
  844. /*  netxopen
  845. *   Open a network socket for the user.
  846. *
  847. */
  848. int netxopen
  849.   (
  850.     uint32 *machine,
  851.     uint service,
  852.     uint rto,
  853.     uint mtu,
  854.     uint mseg,
  855.     uint mwin
  856.   )
  857. {
  858. #pragma unused(rto, mtu, mseg, mwin)
  859.     int    pnum;
  860.     StreamRPtr p;
  861.     TCPiopb *pbp;
  862.     char temp[100];
  863.     
  864.     pnum = makestream();
  865.  
  866.     if (pnum < 0)
  867.         return(-2);
  868.  
  869.     if (NULL == (p = streams[pnum]))
  870.         return(-2);
  871.  
  872.     pbp=getPB( TCPd, TCPActiveOpen, p->stream, pnum);            /* Make Listen call */
  873.     
  874.     pbp->csParam.open.remoteHost = *machine;            /* IP # */
  875.     pbp->csParam.open.remotePort = service;                /* Port */
  876.     pbp->csParam.open.localPort = nnfromport;            /* My Port */
  877.     nnfromport=0;                                            /* Next one is random */
  878.     
  879.     pbp->ioCompletion = (TCPIOCompletionProc) openComplete;    /* IO Completion for open */
  880.     
  881.     if (PBControl((ParmBlkPtr) pbp, Qcall) != noError) {
  882.         putln("TCPOpen failed(Active)"); return(-1);
  883.         }
  884.     sprintf(temp,"TCPOpen on %d",pnum);
  885.     putln(temp);
  886.     return(pnum);
  887. }
  888.  
  889. /**************************************************************************/
  890. /*  netopen
  891. *   Netopen is a cheap way to open a connection without looking up any
  892. *   machine information.  Uses suitable default values for everything.
  893. */
  894. netopen(s,tport)
  895. unsigned char *s;
  896. uint tport;
  897. {
  898.  
  899.     return(netxopen((uint32 *) s,tport,MINRTO,TSENDSIZE,DEFSEG,DEFWINDOW));
  900. }
  901.  
  902.  
  903. /**************************************************************************/
  904. /* netclose
  905. *  Do appropriate actions to return connection state to SCLOSED which
  906. *  enables the memory for that port to be reused.
  907. *
  908. *    Specifically:
  909. *        o If status is closed, then release the data structures
  910. *        o If status is not close, perform bkgrd close which generates CLOSEDONE,
  911. *            which should make the session layer call us again
  912. */
  913. int netclose
  914.   (
  915.     int pnum
  916.   )
  917. {
  918.     StreamRPtr p;
  919.     TCPiopb *pbp;
  920.     int errorCode=0;
  921.     int status;
  922.     char temp[50];
  923.     static short count=0;
  924.     
  925.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  926.         return(-1);
  927.  
  928.     if ((p = streams[pnum]) == NULL)             /* nothing there */
  929.         return (1);
  930.  
  931.     pbp=getPB( TCPd, TCPStatus, p->stream, pnum);            /* Make status call */
  932.     if ((errorCode = PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  933.         if ( errorCode == invalidStreamPtr) {
  934.             putln("TCPStatus failed because of bad stream pointer (close)");
  935.             return(-1);
  936.             }
  937.         else
  938.             {
  939.             status=0;
  940.             count =0;
  941.             }
  942.         }
  943.     else 
  944.         {
  945.         status = pbp->csParam.status.connectionState;            /* The connection Status */
  946.         if (count++ ==10) status=count =0;
  947.         }
  948.  
  949. /* */
  950.  
  951.     sprintf(temp,"the error Code is %i",(int)errorCode);
  952.     putln(temp);
  953.  
  954.     if (status < 18 && status >2 ) {                            /* We aren't closed yet ! */
  955.         char temp[50];
  956.         sprintf(temp, "TCPClose being attempted state ...[%d]",status);    /* Prolly because outstanding close */
  957.         putln(temp);
  958.         clearPB( pbp, TCPd, TCPClose, p->stream, pnum);            /* Make Close call */
  959.         pbp->ioCompletion = (TCPIOCompletionProc) closeComplete; /* IO Completion for close */
  960.         if ((errorCode=PBControl((ParmBlkPtr) pbp, Qcall)) != noError) {
  961.             char temp[50];
  962.             sprintf(temp, "TCPClose failed...[%d]",errorCode);    /* Prolly because outstanding close */
  963.             putln(temp);
  964.             putln("we have an error");
  965.             return (errorCode); /* */
  966.             }
  967.  
  968.         return (0);                                            /* Return with OK */
  969.         }
  970.  
  971.     /* IF we got here, we must be at closed state, so free memory */
  972.  
  973.     putln("TCP Being Released...... ");
  974.     clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Release call */
  975.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  976.         putln("TCPRelease failed"); return(-1);
  977.         }
  978.     
  979.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  980.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  981.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  982.     streams[pnum]=0L;
  983.  
  984.     returnPB(pbp);
  985.     return(0);
  986. }
  987.  
  988. /**************************************************************************/
  989. /* netabort
  990. *    Nuke the connection, NOW!
  991. */
  992. netabort(pnum)
  993. int pnum;
  994. {
  995.     StreamRPtr p;
  996.     TCPiopb *pbp;
  997.     int errorCode=0;
  998.  
  999.     if (pnum < 0 || pnum > NPORTS)            /* is a valid port? */
  1000.         return(-1);
  1001.  
  1002.     if ((p = streams[pnum]) != NULL) {            /* something there */
  1003.         pbp=getPB( TCPd, TCPAbort, p->stream, pnum);            /* Make Close call */
  1004.         if ((errorCode=PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  1005.             char temp[50];
  1006.             sprintf(temp, "TCPAbort failed...[%d]",errorCode);
  1007.             putln(temp);
  1008.             }
  1009.         clearPB( pbp,TCPd, TCPRelease, p->stream, pnum);            /* Make Close call */
  1010.         if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1011.             putln("TCPRelease failed"); return(-1);
  1012.             }
  1013.         }
  1014.     else
  1015.         return(1);
  1016.     
  1017.     DisposPtr( p->buffer);                /* Free Receive Buffer */
  1018.     DisposPtr( p->sbuffer);                /* Free Send Buffer */
  1019.     DisposPtr((Ptr) p);                    /* Free Stream Structure */
  1020.     streams[pnum]=0L;
  1021.  
  1022.     returnPB(pbp);
  1023.     return(0);
  1024. }
  1025.  
  1026. /**************************************************************************/
  1027. /*  netinit
  1028. *   Calls all of the various initialization routines that set up queueing
  1029. *   variables, static values, reads configuration files, etc.
  1030. */
  1031.  
  1032. int netinit
  1033.   (
  1034.     void
  1035.   )
  1036. {
  1037.     int i;
  1038. extern Cursor *normcurs;
  1039.     
  1040.     for (i=0; i<NPORTS;i++)
  1041.         streams[i]= (StreamRPtr) 0;
  1042.         
  1043.     for (i=0; i<NPORTS;i++)
  1044.         uport[i]= (UDPRPtr) 0;
  1045.     
  1046.     if (opendriver(".IPP",&TCPd) != noError) {
  1047.         SetCursor(normcurs);
  1048.         putln( "Couldn't open IP driver ");
  1049.         OtherError("Error opening TCP drivers.","Possibly no dynamic addressing");
  1050.         quit();
  1051.         }
  1052.         
  1053.     return(0);                /* set up empty packets */
  1054. }
  1055.  
  1056. /**************************************************************************/
  1057. int UDPfindport( port)
  1058. int port;
  1059. {
  1060.     int pnum=0;
  1061.     
  1062.     while (pnum<NPORTS &&
  1063.             ( uport[pnum] ==(UDPRPtr)0L || port !=uport[pnum]->port))
  1064.         pnum++;
  1065.     if (pnum >=NPORTS)
  1066.         return(-1);
  1067.     else
  1068.         return(pnum);
  1069. }
  1070.  
  1071. /**************************************************************************/
  1072. /*
  1073.  * netuclose( port)             - close the udp port 
  1074.  */
  1075.  
  1076. netuclose( port)
  1077. int port;
  1078. {
  1079.     UDPRPtr p;
  1080.     UDPiopb *pbp;
  1081.     int pnum;
  1082.     
  1083.     pnum= UDPfindport( port);
  1084.     
  1085.     if (pnum<0)
  1086.         return(-1);
  1087.     
  1088.     p=uport[pnum];
  1089.     
  1090.     pbp = getUPB( TCPd, UDPRelease, p->stream, 0);
  1091.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1092.         putln("UDPClose failed"); return(-1);
  1093.         }
  1094.     DisposPtr( p->buffer);
  1095.     DisposPtr((Ptr) uport[pnum]);
  1096.     uport[pnum]=0;                /* use me again */
  1097.     
  1098.     returnPB( pbp);
  1099. }
  1100.  
  1101. /*************************************************************************/
  1102. /*  netshut
  1103. *   Close all the connections and turn off the hardware.
  1104. */
  1105. netshut()
  1106.     {
  1107.     int i;
  1108.  
  1109.     for (i=0; i < NPORTS ; i++) 
  1110.         if (streams[i] != (StreamRPtr) NULL)
  1111.             netabort(i);                        /* Prolly should abort */
  1112.     for (i=0; i < NPORTS ; i++) 
  1113.         if (uport[i] != (UDPRPtr) NULL)
  1114.             netuclose(uport[i]->port);            /* Shut down UDP too... */
  1115. #ifdef SAFE
  1116.     CloseDriver( TCPd);
  1117. #endif SAFE
  1118. }
  1119.  
  1120. /**************************************************************************/
  1121. int findbystream( streamPtr)
  1122. StreamPtr streamPtr;
  1123. {
  1124.     int pnum=0;
  1125.     
  1126.     while (pnum<NPORTS &&
  1127.             ( (streams[pnum] ==(StreamRPtr)0L) || (streamPtr !=streams[pnum]->stream)))
  1128.         pnum++;
  1129.     if (pnum >=NPORTS)
  1130.         return(-1);
  1131.     else
  1132.         return(pnum);
  1133. }
  1134.  
  1135.  
  1136. /**************************************************************************/
  1137. pascal void TCPNotify( streamPtr, code, uptr, terminReason, icmpMsg)
  1138. StreamPtr streamPtr;
  1139. unsigned short /*enum  TCPEventCode*/ code;
  1140. unsigned short /*enum  TCPTerminationReason*/ terminReason;
  1141. struct ICMPReport *icmpMsg;
  1142. Ptr uptr;   /* user data pointer */
  1143. {
  1144. #pragma unused(uptr, terminReason, icmpMsg)
  1145.     StreamRPtr p;
  1146.     int pnum;
  1147.     
  1148.     pnum = findbystream(streamPtr);
  1149.     
  1150.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1151.         return;
  1152.     
  1153.     switch( code) {
  1154.         case TCPTerminate:
  1155.         case TCPClosing:
  1156.             netputevent(CONCLASS, CONCLOSE, pnum);
  1157.             break;
  1158.         case TCPULPTimeout:
  1159.             netputevent(CONCLASS, CONFAIL, pnum);
  1160.             break;
  1161.         case TCPDataArrival:
  1162.         case TCPUrgent:
  1163.             netputuev(CONCLASS, CONDATA, pnum);
  1164.             break;
  1165.         case TCPICMPReceived:
  1166.         default:
  1167.             break;
  1168.         }
  1169.     return;
  1170. }
  1171.  
  1172. /*************************************************************************/
  1173. /*  netopen2
  1174. *   Send out repeat SYN on a connection which is not open yet
  1175. *   Checks, and only sends one if needed.
  1176. *   Returns 1 if the state is still SYNS and 0 if the connection has proceeded.
  1177. *   The timing is all handled at a higher layer.
  1178. */
  1179. int netopen2
  1180.   (
  1181.     int pnum
  1182.   )
  1183. {
  1184.     return( netest(pnum));
  1185. }
  1186.  
  1187. /**************************************************************************/
  1188. long openComplete( pbp)
  1189. TCPiopb *pbp;
  1190. {
  1191.     StreamRPtr p;
  1192.     int pnum;
  1193.     
  1194.     pnum= findbystream(pbp->tcpStream);
  1195.     
  1196.     if (pnum < 0 || (p = streams[pnum]) == 0L) 
  1197.         return(-1);
  1198.         
  1199.     if (pbp->ioResult !=noError) 
  1200.         netputevent(CONCLASS, CONFAIL, pnum);            /* Failure ... */
  1201.     else 
  1202.         netputevent(CONCLASS, CONOPEN, pnum);            /* Success ! */
  1203.  
  1204.     returnPB( pbp);
  1205.     return(0);
  1206. }
  1207.  
  1208. /**************************************************************************/
  1209. /*
  1210.  *    giveback( p, wds) -
  1211.  *        gives WDS entries back to the stream by putting them in the 
  1212.  *        mutually exclusive buffer.
  1213.  *    p -> stream
  1214.  *    wds -> wds array
  1215.  */
  1216. giveback( p, wds)
  1217. StreamRPtr p;
  1218. wdsEntry *wds;
  1219. {
  1220.     int n=0, m=0;
  1221.     
  1222.     while ( n< MAX_SWDS_ELEMS && wds[n].ptr !=0L) {
  1223.         while (m< MAX_FDS_ELEMS && p->exFDS[ m].inuse) m++;
  1224.         if (m> MAX_FDS_ELEMS)
  1225.             return(-1);                /* No room in the RECLAIMation center */
  1226.         else {
  1227.             p->exFDS[ m].inuse =1;
  1228.             p->exFDS[ m].fds = wds[n];
  1229.             m++;
  1230.             }
  1231.         n++;
  1232.         }
  1233. }
  1234.  
  1235.  
  1236. /**************************************************************************/
  1237. long sendComplete( pbp)
  1238. TCPiopb *pbp;
  1239. {
  1240.     StreamRPtr p;
  1241.     int pnum;
  1242.     wdsEntry *swds;
  1243.     int i=0,j=0;
  1244.     
  1245.     (Ptr) swds = pbp->csParam.send.wdsPtr;
  1246.     
  1247.     pnum= findbystream(pbp->tcpStream);
  1248.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1249.         return(-1);
  1250.  
  1251.     returnSWDS( swds);
  1252.     returnPB( pbp);
  1253.  
  1254.     giveback( p, pbp->csParam.send.wdsPtr);            /* Give this back.... NOW */
  1255.     
  1256.     return(0);
  1257. }
  1258.  
  1259.  
  1260. /**************************************************************************/
  1261. long closeComplete( pbp)
  1262. TCPiopb *pbp;
  1263. {
  1264.     StreamRPtr p;
  1265.     int pnum;
  1266.     
  1267.     pnum= findbystream(pbp->tcpStream);
  1268.     
  1269.     if (pnum < 0 || (p = streams[pnum]) == 0L)
  1270.       {
  1271.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1272.         return(-1);
  1273.       }
  1274.         
  1275.     if (pbp->ioResult !=noError) 
  1276.         netputevent(SCLASS, CLOSEDONE+1, pnum);
  1277.     else 
  1278.         netputevent(SCLASS, CLOSEDONE, pnum);            /* Success ! */
  1279.  
  1280.     returnPB( pbp);
  1281.     return(0);
  1282. }
  1283.  
  1284.  
  1285.  
  1286. /*****************************************************************************
  1287.  *
  1288.  * Here lie the awful UDP routines, I put them here for the drivers from Apple.
  1289.  *
  1290.  */
  1291.  
  1292.  int UDPlisten =0;                /* what port the old routines listen for */
  1293.  
  1294.  
  1295. /****************************************************************************/
  1296. /*                    New UDP routines....                                    */
  1297. /****************************************************************************/
  1298.  
  1299. /**************************************************************************/
  1300. makeuport( port)
  1301. int port;
  1302. {
  1303.     int    pnum;
  1304.     UDPRPtr p;
  1305.     UDPiopb *pbp;
  1306.     int i;
  1307.     
  1308.     for ( pnum=0; uport[pnum]!= NULL && pnum<NPORTS; pnum++);
  1309.     
  1310.     if (pnum >= NPORTS)
  1311.         return(-2);
  1312.  
  1313.     p = uport[pnum] = (UDPRPtr) NewPtr(sizeof(UDPRec));
  1314.  
  1315.     if ((p->buffer = (char *) NewPtr( UDPBUFSIZ)) == (char *)NULL)
  1316.         return(-1);
  1317.     
  1318.     
  1319.     pbp=getUPB( TCPd, UDPCreate, 0, pnum);            /* Make create call */
  1320.     
  1321.     pbp->csParam.create.rcvBuff  = p->buffer;
  1322.     pbp->csParam.create.rcvBuffLen= UDPBUFSIZ;
  1323.     pbp->csParam.create.notifyProc     = UDPNotify;
  1324.     pbp->csParam.create.localPort = port;
  1325.     
  1326.     if ((i=PBControl((ParmBlkPtr) pbp, noQcall)) != noError) {
  1327.         char temp[50];
  1328.         sprintf(temp, "UDPCreate failed (%d)",i);
  1329.         putln(temp);
  1330.         return(-1);
  1331.         }
  1332.     else {
  1333.         char temp[50];
  1334.         sprintf(temp, "UDPCreate successfull on %d(%d) [%x]",port,pnum,pbp->udpStream);
  1335.         putln(temp);
  1336.         }
  1337.     
  1338.     p->stream = pbp->udpStream;
  1339.     p->port = port;
  1340.     
  1341.     putln("Made a new UPORT");
  1342.     returnPB(pbp);
  1343.     return(pnum);
  1344. }
  1345.  
  1346. /**************************************************************************/
  1347. /*
  1348.  * netuopen (port)             - open the udp port "Port"
  1349.  */
  1350.  
  1351. netuopen(port)
  1352. int port;
  1353. {
  1354.     return(makeuport( port));
  1355. }
  1356.  
  1357. /**************************************************************************/
  1358. /*
  1359.  *    netuget( port, buffer,len, who,where)
  1360.  *                    - read up to len bytes from port port into buffer buffer, noting
  1361.  *                        who it was from and where....
  1362.  */
  1363.  
  1364. netuget( port, buffer, len, who, where)
  1365. int port, len;
  1366. int *who, *where;
  1367. char *buffer;
  1368. {
  1369. #pragma unused(who, where)
  1370.     int pnum, length;
  1371.     UDPRPtr p;
  1372.     UDPiopb *pbp;
  1373.     
  1374.     pnum= UDPfindport( port);
  1375.     
  1376.     if (pnum<0)
  1377.         return(-1);
  1378.     
  1379.     p=uport[pnum];
  1380.     
  1381.     pbp= getUPB( TCPd, UDPRead, p->stream, 0);
  1382.     pbp->csParam.receive.timeOut = 1;                            /* time out at one sec. */
  1383.     
  1384.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1385.         putln("UDPRead failed"); return(-1);
  1386.         }
  1387.     
  1388.     length = pbp->csParam.receive.rcvBuffLen;                /* look how BIG it is */
  1389.     length = length > len ? len:length;
  1390.     
  1391.     memcpy( buffer, pbp->csParam.receive.rcvBuff,length);
  1392.     
  1393.     pbp->csCode = UDPBfrReturn;                                /* Let my buffer go.. */
  1394.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1395.         putln("UDPReturn failed"); return(-1);
  1396.         }
  1397.         
  1398.     returnPB( pbp);
  1399.     
  1400.     return(length);
  1401. }
  1402.  
  1403. /**************************************************************************/
  1404. netuput( machine, port, myport, buffer, n)
  1405. long *machine;
  1406. char *buffer;
  1407. int port, myport;
  1408. int n;
  1409. {
  1410.     wdsEntry wds[2];
  1411.     UDPRPtr p;
  1412.     UDPiopb *pbp; int pnum;
  1413.     
  1414.     pnum= UDPfindport( myport);
  1415.     
  1416.     if (pnum<0)
  1417.         return(-1);
  1418.     
  1419.     p=uport[pnum];
  1420.     
  1421.     pbp= getUPB( TCPd, UDPWrite, p->stream, 0);
  1422.     pbp->csParam.send.remoteHost = *machine;
  1423.     pbp->csParam.send.remotePort = port;
  1424.     pbp->csParam.send.checkSum   = 1;                    /* Do do that checksum that you do so well */
  1425.     pbp->csParam.send.wdsPtr = (Ptr) wds;
  1426. /*    pbp->csParam.send.remoteHost = *machine;    /* BYU - not needed, done above. */
  1427.     
  1428.     wds[0].ptr = buffer;
  1429.     wds[0].length=n;
  1430.     wds[1].ptr = (char *) 0L; wds[1].length=0;
  1431.     
  1432.     if (PBControl((ParmBlkPtr) pbp, noQcall) != noError) {
  1433.         putln("UDPReturn failed"); return(-1);
  1434.         }
  1435.         
  1436.     returnPB( pbp);
  1437.     return(0);
  1438. }
  1439.  
  1440.  
  1441. /****************************************************************************/
  1442. /*  neturead
  1443. *   get the data from the UDP buffer
  1444. *   Returns the number of bytes transferred into your buffer, -1 if none here
  1445. *   This needs work.
  1446. */
  1447. int neturead
  1448.   (
  1449.     char *buffer
  1450.   )
  1451. {
  1452.     int who, where;
  1453.     
  1454.     if (!UDPlisten)
  1455.         return(-1);
  1456.         
  1457.     return( netuget( UDPlisten, buffer, 512, &who, &where));
  1458. }
  1459.  
  1460. /***************************************************************************/
  1461. /*  netulisten
  1462. *   Specify which UDP port number to listen to.
  1463. *   Can only listen to one at a time.
  1464. */
  1465. int netulisten
  1466.   (
  1467.     int port
  1468.   )
  1469. {
  1470.     char temp[50];
  1471.     int pnum;
  1472.  
  1473.     
  1474.     sprintf( temp, "UDP listening on ....%d", port);
  1475.     putln(temp);
  1476.     
  1477.     UDPlisten = port;
  1478.     
  1479.     if ( (pnum=UDPfindport( port))<0)
  1480.         pnum= netuopen(port);
  1481.     
  1482.     return (pnum);
  1483. }
  1484.  
  1485. /***************************************************************************/
  1486. /*  netusend
  1487. *   send some data out in a UDP packet
  1488. *   uses the preinitialized data in the port packet ulist.udpout
  1489. *   
  1490. *   returns 0 on okay send, nonzero on error
  1491. */
  1492. void netusend
  1493.   (
  1494.     unsigned char *machine,
  1495.     unsigned int port,
  1496.     unsigned int retport,
  1497.     unsigned char *buffer,
  1498.     int n
  1499.   )
  1500. {
  1501.     /* find if port is open */
  1502.     if ( UDPfindport( retport)<0)
  1503.         netuopen(retport);
  1504.     
  1505.     /* Send data */
  1506.     netuput( machine, port, retport, buffer,n);
  1507. }
  1508.  
  1509. /**************************************************************************/
  1510. int ufindbystream( streamPtr)
  1511. StreamPtr streamPtr;
  1512. {
  1513.     int pnum=0;
  1514.     
  1515.     while (pnum<NPORTS &&
  1516.             ( uport[pnum] ==(UDPRPtr)0L || streamPtr !=uport[pnum]->stream))
  1517.         pnum++;
  1518.     if (pnum >=NPORTS)
  1519.         return(-1);
  1520.     else
  1521.         return(pnum);
  1522. }
  1523.  
  1524. /**************************************************************************/
  1525. pascal void UDPNotify( streamPtr, code, uptr, icmpMsg)
  1526. StreamPtr streamPtr;
  1527. unsigned short code;
  1528. struct ICMPReport *icmpMsg;
  1529. Ptr uptr;   /* user data */
  1530. {
  1531. #pragma unused(uptr, icmpMsg)
  1532.     UDPRPtr p;
  1533.     int pnum;
  1534.     
  1535.     pnum= ufindbystream(streamPtr);
  1536.     
  1537.     if (pnum < 0 || (p = uport[pnum]) == 0L)
  1538.         return;
  1539.     
  1540.     switch( code) {
  1541.         case UDPDataArrival:
  1542.             netputuev(USERCLASS,UDPDATA,p->port);        /* post that it is here */
  1543.         default:
  1544.             break;
  1545.         }
  1546.     return;
  1547. }
  1548.  
  1549. void netconfig
  1550.   (
  1551.     char *hardware
  1552.   )
  1553. {
  1554. #pragma unused(hardware)
  1555.     putln("I'm a driver TCP, I don't need hardware.....");
  1556.     initipnum(0);
  1557. }
  1558.  
  1559. void netarpme
  1560.   (
  1561.     char *s
  1562.   )
  1563. {
  1564. #pragma unused(s)
  1565.     putln("Drivers don't need arps, either.");
  1566. }
  1567.  
  1568. netsetgate(s)
  1569. char *s;
  1570. {
  1571. #pragma unused(s)
  1572.     putln("Yeah, right....");
  1573.     return
  1574.         0;
  1575. }
  1576.  
  1577. int netgetrarp
  1578.   (
  1579.     void
  1580.   )
  1581. {
  1582.     putln("RARP handled above me....");
  1583.     return
  1584.         0;
  1585. }
  1586.  
  1587. uint8 *getdlayer()
  1588. {
  1589.     putln("This shouldn't be called...");
  1590.     return(0L);
  1591. }
  1592.  
  1593. tcpsend()
  1594. {
  1595. }
  1596.  
  1597. demux()
  1598. {
  1599.     return(0);
  1600. }
  1601.  
  1602. /*************************************************************************/
  1603. /* neteventinit
  1604. *  load up the pointers for the event queue
  1605. *  makes a circular list to follow, required for error messages
  1606. */
  1607. void neteventinit
  1608.   (
  1609.     void
  1610.   )
  1611.     {
  1612.     int i;
  1613.  
  1614.     for (i=0; i < NEVENTS; i++)
  1615.         nnq[i].next = i+1;
  1616.  
  1617.     nnq[NEVENTS-1].next = -1;
  1618.  
  1619.     nnefirst = 0;
  1620.     nnelast = 0;
  1621.     nnefree = 1;
  1622. }
  1623.  
  1624. getATaddress()
  1625. {
  1626. }
  1627.  
  1628. KIPfindgate()
  1629. {
  1630. }
  1631.  
  1632. KIPgetns()
  1633. {
  1634. }
  1635.  
  1636. KIPgetdynam()
  1637. {
  1638. }
  1639.  
  1640. KIPregister()
  1641. {
  1642. }
  1643.